package com.ruoyi.auth.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.ruoyi.auth.config.WxMaConfiguration;
import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.security.annotation.RequiresRoles;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.RemoteUserService;
import com.ruoyi.system.api.model.LoginUser;
import com.tdd.wx.users.api.IWxUserService;
import com.tdd.wx.users.config.DefaultWxUserConfig;
import com.tdd.wx.users.entity.WxUser;
import com.tdd.wx.users.mongo.WxUserHandler;
import com.tdd.wx.users.mongo.WxUserPointRecordHandler;
import com.tdd.wx.users.mongo.WxUserPointRecordRepository;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.time.LocalDate;

/**
 * @author lobyliang
 */
@RestController
@RequestMapping("/wxUser")
@Slf4j
public class WxUserController extends BaseController
{

    //    @Autowired
    //    SysLoginService loginService;
    @Autowired
    WxUserHandler wxUserHandler;
    @Autowired
    private DefaultWxUserConfig defaultWxUserConfig;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private RemoteUserService remoteUserService;
    @Autowired
    IWxUserService wxUserService;

    @Autowired
    WxUserPointRecordHandler wxUserPointRecordHandler;

    @GetMapping("/UnionId/{userId}")
    public R<?> getUnionIdByUserId(@PathVariable Long userId)
    {
        WxUser bySystemUserId = null;
        try
        {
            bySystemUserId = wxUserHandler.findBySystemUserId(userId);
        } catch(Exception e)
        {
            log.error(e.getLocalizedMessage(), e);
            return R.fail(e, "查询用户信息失败");
        }
        if(bySystemUserId != null)
        {
            return R.ok(bySystemUserId.getUnionId());
        } else
        {
            return R.fail("未查询到对应用户");
        }
    }

    /**
     * 登陆接口
     */
    @GetMapping("/login/{appid}/{code}")
    public R<?> login(@PathVariable String appid, @PathVariable String code)
    {
        if(StringUtils.isBlank(code))
        {
            return R.fail("empty jscode");
        }
        final WxMaService wxService = WxMaConfiguration.getMaService(appid);
        try
        {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(code);

            log.info(session.getSessionKey());
            log.info(session.getOpenid());
            //            if(false)
            //            {
            //                throw new WxErrorException("a");
            //            }
            //            WxMaJscode2SessionResult session = new WxMaJscode2SessionResult();
            //            session.setOpenid("1234567890123");
            //            session.setUnionid("1234567890123");
            WxUser wxUser = wxUserHandler.findByUnionId(session.getUnionid());
            if(wxUser == null)
            {
                wxUser = new WxUser();
                wxUser.setUnionId(session.getUnionid());
                wxUser.setOpenId(session.getOpenid());
                wxUserHandler.insert(wxUser);
            }
            if(ObjectUtils.isEmpty(wxUser.getSysUserId()))
            {
                WxUser defaultUser = defaultWxUserConfig.getDefaultUser(wxUser);
                return R.ok(tokenService.createWxToken(defaultUser));
            } else
            {
                String username = wxUser.getSysUserName();
                R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER);
                LoginUser userInfo = userResult.getData();
                return R.ok(tokenService.createToken(userInfo));
            }
        } catch(WxErrorException e)
        {
            log.error(e.getMessage(), e);
            return R.fail(e.toString());
        }
    }

    @GetMapping(value = {"/isExist/{openid}", "/isExist"})
    @ApiOperation("查询微信用户是否存在")
    public AjaxResult isWxUserExist(@PathVariable(value = "openid", required = false) String open_id)
    {
        if(open_id == null)
        {
            open_id = SecurityUtils.getOpenId();
        }
        return AjaxResult.success(wxUserService.isWxUserExist(open_id));
    }

    @GetMapping(value = {"/bySystemUserId/{openid}", "/bySystemUserId"})
    @ApiOperation("查询微信用户信息-ry-SystemId")
    public AjaxResult findBySystemUserId(@PathVariable(value = "openid",required = false) Long user_id)
    {
        if(user_id == null)
        {
            user_id = SecurityUtils.getUserId();
        }
        try
        {
            WxUser bySystemUserId = wxUserService.findBySystemUserId(user_id);
            return AjaxResult.success(bySystemUserId);
        } catch(Exception e)
        {
            log.error("操作失败" + e.getLocalizedMessage(), e);
            return AjaxResult.error(e.getLocalizedMessage());
        }
    }
    @GetMapping(value = {"/byOpenId/{openid}", "/byOpenId"})
    @ApiOperation("查询微信用户信息-OpenId")
    public AjaxResult findByOpenId(@PathVariable(value = "openid",required = false) String open_id)
    {
        if(open_id == null)
        {
            open_id = SecurityUtils.getOpenId();
        }
        try
        {
            WxUser byOpenId = wxUserService.findByOpenId(open_id);
            return AjaxResult.success(byOpenId);
        } catch(Exception e)
        {
            log.error("操作失败" + e.getLocalizedMessage(), e);
            return AjaxResult.error(e.getLocalizedMessage());
        }
    }
    @GetMapping(value = {"/byUnionId/{unionid}", "/byUnionId"})
    @ApiOperation("查询微信用户信息-UnionId")
    public AjaxResult findByUnionId(@PathVariable(value = "unionid",required = false) String unionid)
    {
        if(unionid == null)
        {
            unionid = SecurityUtils.getUnionId();
        }
        try
        {
            WxUser byUnionId = wxUserService.findByUnionId(unionid);
            return AjaxResult.success(byUnionId);
        } catch(Exception e)
        {
            log.error("操作失败" + e.getLocalizedMessage(), e);
            return AjaxResult.error(e.getLocalizedMessage());
        }
    }
    @GetMapping(value = {"/ByShareUnionId/{unionid}", "/ByShareUnionId"})
    @ApiOperation("查询微信用户信息-分享人")
    public TableDataInfo findByShareUnionId(@PathVariable(value = "unionid",required = false) String union_id)
    {
        if(union_id == null)
        {
            union_id = SecurityUtils.getUnionId();
        }
        try
        {
            return getDataTable(wxUserService.findByShareUnionId(union_id));
        } catch(Exception e)
        {
            log.error("操作失败" + e.getLocalizedMessage(), e);
            return getFaultDataTable(e.getLocalizedMessage());
        }
    }
    @GetMapping(value = {"/byOrigin/{origin}"})
    @ApiOperation("查询微信用户信息-来源来源0：未知，1：出袋小程序，2.广告投放小程序，3.运维APP，4.广告投放网站，5.管理中台")
    public TableDataInfo findByOrigin(@PathVariable("origin") int origin)
    {
        try
        {
            return getDataTable(wxUserService.findByOrigin(origin));
        } catch(Exception e)
        {
            log.error("操作失败" + e.getLocalizedMessage(), e);
            return getFaultDataTable(e.getLocalizedMessage());
        }
    }

    @PostMapping()
    @ApiOperation("新建微信用户信息")
    public AjaxResult save(@RequestBody WxUser user)
    {
        try
        {
            if(user!=null)
            {
                wxUserService.save(user);
                return AjaxResult.success();
            }
            return AjaxResult.error("用户信息为空");
        } catch(Exception e)
        {
            log.error("操作失败" + e.getLocalizedMessage(), e);
            return AjaxResult.error(e.getLocalizedMessage());
        }
    }

    @PutMapping()
    @ApiOperation("更新微信用户信息")
    public AjaxResult update(@RequestBody WxUser user)
    {
        try
        {
            wxUserService.update(user);
            return AjaxResult.success();
        } catch(Exception e)
        {
            log.error("操作失败" + e.getLocalizedMessage(), e);
            return AjaxResult.error(e.getLocalizedMessage());
        }
    }

    @DeleteMapping("/{openid}")
    @ApiOperation("删除微信用户信息")
    public AjaxResult delByOpenId(@PathVariable("openid") String open_id)
    {
        try
        {
            wxUserService.delByOpenId(open_id);
            return AjaxResult.success();
        } catch(Exception e)
        {
            log.error("操作失败" + e.getLocalizedMessage(), e);
            return AjaxResult.error(e.getLocalizedMessage());
        }
    }

    @RequiresRoles("admin")
    @PostMapping("/all")
    @ApiOperation("获取所有用户信息,order=>0升序")
    public TableDataInfo findAll(@RequestParam("pageSize")int pageSize,@RequestParam("pageNo") int pageNo,@RequestBody WxUser example,@RequestParam("order") Integer order)
    {
        try
        {
            return getDataTable(wxUserService.findAll(pageSize, pageNo, example, order));
        } catch(Exception e)
        {
            log.error("操作失败" + e.getLocalizedMessage(), e);
            return getFaultDataTable(e.getLocalizedMessage());
        }
    }

    private TableDataInfo getFaultDataTable(String msg)
    {
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.ERROR);
        rspData.setMsg(msg);
        return rspData;
    }
    @PutMapping(value = {"/points/{point}/{unionId}","/points/{point}"})
    @ApiOperation("增加积分")
    public AjaxResult increasePoints(@PathVariable(value = "unionId",required = false) String unionId, @PathVariable("point") Integer point)
    {
        if(unionId == null)
        {
            unionId = SecurityUtils.getUnionId();//.getOpenId();
        }
        try
        {
            Integer newPoints = wxUserService.increasePoints(unionId, point);
            return AjaxResult.success(newPoints);
        } catch(Exception e)
        {
            log.error("操作失败" + e.getLocalizedMessage(), e);
            return AjaxResult.error(e.getLocalizedMessage());
        }
    }

    @PutMapping(value = {"/points/consume/{point}/{unionId}","/points/consume/{point}"})
    @ApiOperation("使用积分")
    public AjaxResult consumePoints(@PathVariable(value = "unionId",required = false) String unionId, @PathVariable("point") Integer point)
    {
        if(unionId == null)
        {
            unionId = SecurityUtils.getUnionId();//.getOpenId();
        }
        try
        {
            Integer leftPoints = wxUserService.consumePoints(unionId, point);
            return AjaxResult.success(leftPoints);
        } catch(Exception e)
        {
            log.error("操作失败" + e.getLocalizedMessage(), e);
            return AjaxResult.error(e.getLocalizedMessage());
        }
    }
    @PutMapping(value = {"/level/upgrade/{plusLevel}/{unionId}","/level/upgrade/{plusLevel}"})
    @ApiOperation("用户升级")
    public AjaxResult userUpgrade(@PathVariable(value = "unionId",required = false) String unionId, @PathVariable("plusLevel") Integer plusLevel)
    {
        if(unionId == null)
        {
            unionId = SecurityUtils.getUnionId();//.getOpenId();
        }
        try
        {
            Integer newLevle = wxUserService.userUpgrade(unionId, plusLevel);
            return AjaxResult.success(newLevle);
        } catch(Exception e)
        {
            log.error("操作失败" + e.getLocalizedMessage(), e);
            return AjaxResult.error(e.getLocalizedMessage());
        }
    }

    @GetMapping(value = {"/new/byUnionId/{unionId}","/new/byUnionId"})
    @ApiOperation("查找用户信息-外包")
    public AjaxResult newFindByUnionId(@PathVariable(value = "unionId",required = false) String unionId)
    {
        try
        {
            WxUser wxUser = wxUserService.newFindByUnionId(unionId);
            AjaxResult.success(wxUser);
        } catch(Exception e)
        {
            log.error("操作失败" + e.getLocalizedMessage(), e);
            return AjaxResult.error(e.getLocalizedMessage());
        }
        return AjaxResult.error();
    }
    @PutMapping(value = {"/new"})
    @ApiOperation("更新用户信息-外包")
    public AjaxResult updateWxUser(@RequestBody WxUser wxUser)
    {
        try
        {
            wxUserService.updateWxUser(wxUser);
        } catch(Exception e)
        {
            log.error("操作失败" + e.getLocalizedMessage(), e);
            return AjaxResult.error(e.getLocalizedMessage());
        }
        return AjaxResult.error();
    }

    @PutMapping(value = {"/bagsLeftToday/{admCode}/{unionId}","/bagsLeft/{admCode}"})
    @ApiOperation("今日可领垃圾袋数量")
    public AjaxResult getUserBagLeft(@PathVariable(value = "unionId",required = false) String unionId, @PathVariable("admCode") String admCode)
    {
        if(unionId == null)
        {
            unionId = SecurityUtils.getUnionId();
        }
        try
        {
            int userBagLeft = wxUserService.getUserBagLeft(unionId, admCode);
            return AjaxResult.success(userBagLeft);
        } catch(Exception e)
        {
            log.error("操作失败" + e.getLocalizedMessage(), e);
            return AjaxResult.error(e.getLocalizedMessage());
        }
    }

    @PutMapping(value = {"/receiveBagAmount/{amount}/{openid}", "/receiveBagAmount/{amount}"})
    @ApiOperation("领取垃圾袋数量及时间")
    public AjaxResult updateReceiveBagAmount(@PathVariable(value = "openid",required = false) String openId, @PathVariable("amount") int amount)
    {
        if(openId == null)
        {
            openId = SecurityUtils.getOpenId();
        }
        try
        {
            wxUserService.updateReceiveBagAmount(openId, amount);
        } catch(Exception e)
        {
            log.error("操作失败" + e.getLocalizedMessage(), e);
            return AjaxResult.error(e.getLocalizedMessage());
        }
        return AjaxResult.success();
    }

    @ApiOperation("记录出袋完成")
    @PutMapping("/recordGiveOutBagComplete/{operateUserUnionId}/{bagAmount}")
    public AjaxResult recordGiveOutBagComplete(@PathVariable("operateUserUnionId") String operateUserUnionId, @PathVariable("bagAmount")int bagAmount)
    {
        try{
            WxUser user = wxUserHandler.findByUnionId(operateUserUnionId);
            if(user!=null){
                user.setReceiveBagAmount(bagAmount);
                user.setLastGetBagDate(LocalDate.now());
                user.increasePoint(bagAmount);//todo 看看会不会重复记录积分
                wxUserPointRecordHandler.save(operateUserUnionId, "领袋子", "get_bag", BigDecimal.valueOf(bagAmount));
                wxUserHandler.update(user);
                return AjaxResult.success(user.getUserPoints());
            }
            else
            {
                log.debug("未找到用户:{}",operateUserUnionId);
            }
        }catch(Exception e)
        {
            log.error("记录出袋失败",e);
            return AjaxResult.error(e.getLocalizedMessage());
        }
        return AjaxResult.error("未找到微信用户");
    }

    @ApiOperation("按系统用户ID查找")
    @GetMapping("/getBySystemUserId/{sysUserId}")
    public WxUser getBySystemUserId( @PathVariable("sysUserId")Long sysUserId)
    {
        return wxUserHandler.findBySystemUserId(sysUserId);
    }

    //    /**
    //     * <pre>
    //     * 获取用户信息接口
    //     * </pre>
    //     */
    //    @GetMapping("/info/{appid}")
    //    public R<?> info(@PathVariable String appid, String sessionKey, String signature, String rawData, String encryptedData, String iv){
    //        final WxMaService wxService = WxMaConfiguration.getMaService(appid);
    //
    //        // 用户信息校验
    //        if(! wxService.getUserService().checkUserInfo(sessionKey, rawData, signature)){
    //            return R.fail("user check failed");
    //        }
    //
    //        // 解密用户信息
    //        WxMaUserInfo userInfo = wxService.getUserService().getUserInfo(sessionKey, encryptedData, iv);
    //        if(!ObjectUtils.isEmpty(userInfo.getOpenId()))
    //        {
    //            WxUser wxUser = wxUserHandler.findByOpenId(userInfo.getOpenId());
    //            if(ObjectUtils.isEmpty(wxUser))
    //            {
    //                wxUser = new WxUser();
    //                wxUser.setOpenId(userInfo.getOpenId());
    //                wxUser.setUnionId(userInfo.getUnionId());
    //                wxUser.setCreateDate(LocalDateTime.now());
    //            }
    //            wxUser.setAvatar(userInfo.getAvatarUrl());
    //            wxUser.setCountry(userInfo.getCountry());
    //            wxUser.setProvince(userInfo.getProvince());
    //            wxUser.setCity(userInfo.getCity());
    //            wxUser.setNickName(userInfo.getNickName());
    //            wxUser.setGener(userInfo.getGender());
    //            wxUserHandler.save(wxUser);
    //            return R.ok(wxUser);
    //        }
    //        return R.fail("未找到该用户");
    //    }
    //
    //    /**
    //     * <pre>
    //     * 获取用户绑定手机号信息
    //     * </pre>
    //     */
    //    @GetMapping("/phone/{appid}")
    //    public R<?> phone(@PathVariable String appid, String sessionKey, String signature, String rawData, String encryptedData, String iv){
    //        final WxMaService wxService = WxMaConfiguration.getMaService(appid);
    //
    //        // 用户信息校验
    //        if(! wxService.getUserService().checkUserInfo(sessionKey, rawData, signature)){
    //            return R.fail("user check failed");
    //        }
    //        // 解密
    //        WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);
    //        return R.ok(phoneNoInfo);
    //    }

    //    public void a()
    //    {
    //        wxUserService.updateReceiveBagAmount();
    //        wxUserService.getUserBagLeft();
    //        wxUserService.update();
    //        wxUserService.userUpgrade();
    //        wxUserService.consumePoints();
    //        wxUserService.delByOpenId();
    //        wxUserService.findAll();
    //        wxUserService.findByOpenId();
    //        wxUserService.findByOrigin();
    //        wxUserService.findBySystemUserId();
    //        wxUserService.findByUnionId();
    //        wxUserService.findByShareUnionId();
    //        wxUserService.increasePoints();
    //        wxUserService.isWxUserExist()
    //    }
}
